import { reactive, ref, shallowRef } from 'vue';
import cloneDeep from 'lodash/cloneDeep';
import { getTopologyDetail } from '@/api/topo/topo';
import {
  builtBaseNode,
  builtBaseNodeMap,
} from './config';
import { Graph } from '@antv/x6';
import { getCopyTopologyDetail } from '@/api/topo/copy';
import { simulationCover } from '../defaultConfig';
import { emitter } from '@/utils/bus';

export default function RegisterNode() {
  Graph.registerNode(
    'org-node',
    {
      width: '100%',
      height: '100%',
      markup: [
        {
          tagName: 'image',
          attrs: {
            class: 'image',
          },
        },
        {
          tagName: 'rect',
          attrs: {
            class: 'rank',
          },
        },
        {
          tagName: 'image',
          attrs: {
            class: 'rankCenter',
          },
        },
        {
          tagName: 'text',
          attrs: {
            class: 'name',
          },
        },
      ],
      attrs: {
        '.rank': {
          height: 10,
          width: 10,
          xAlign: 'right',
          yAlign: 'top',
          fill: '',
          refX: '100%',
          refY: '0%',
        },
      },
    },
    true,
  );
}

RegisterNode();

export const cellList = reactive({
  nodes: [],
  edges: [],
});

// 载体
export const contextMenu = shallowRef(null);
// 控制显示
export const contextVisible = ref(false);
// 其他配置项
export const contextData = shallowRef(null);
export const contextState = reactive({
  options: {
    modifiers: [
      {
        name: 'offset',
        options: {
          // offset: [40, -20],
        },
      },
    ],
  },
  type: 'node',
});
export const setContext = (type, view, data, options) => {
  if (type !== '') {
    contextState.type = type;
  }
  contextMenu.value = view.container;
  contextData.value = data;
  if (options) {
    const { x, y } = options;
    contextState.options.modifiers[0].options.offset = [x, y];
  }
};
// eslint-disable-next-line no-return-assign
export const showContext = arg => {
  contextVisible.value = arg;
};

export async function refreshGraph(ID, graph) {
  const sceneDetail = ref({});
  const resDetail = await getTopologyDetail(ID);
  if (!(resDetail instanceof Error)) {
    const topoData = {
      clusterID: resDetail.data.clusterID,
      edges: [],
      nodes: [],
    };
    let topoRes = await topoDataHandle(resDetail);
    topoData.edges = topoRes.edges;
    topoData.nodes = topoRes.nodes;

    emitter.emit('topoData', JSON.stringify(resDetail.data));

    graph.fromJSON(topoData);
    sceneDetail.value = resDetail.data;
    return sceneDetail;
  } else {
    graph?.clearCells();
  }
}

export async function copyRefreshGraph(ID, graph) {
  const clusterID = ref(0);
  const resDetail = await getCopyTopologyDetail(ID);
  if (!(resDetail instanceof Error)) {
    const topoData = {
      clusterID: resDetail.data.clusterID,
      edges: [],
      nodes: [],
    };
    let topoRes = await topoDataHandle(resDetail);
    topoData.edges = topoRes.edges;
    topoData.nodes = topoRes.nodes;
    graph.fromJSON(topoData);
    clusterID.value = resDetail.data.clusterID;
    return clusterID;
  } else {
    graph?.clearCells();
  }
}

export const topoDataHandle = async resDetail => {
  const topoData = {
    edges: [],
    nodes: [],
  };
  // 节点数据
  for (const key in resDetail.data.nodes) {
    const commonAttrs = {
      '.name': {
        fill: '#666666',
        fontFamily: 'Arial',
        fontSize: 12,
        refX: '50%',
        refY: '100%',
        xAlign: 'middle',
        yAlign: 'bottom',
      },
      '.image': {
        refHeight2: '90%',
        refWidth2: '90%',
        refX: '50%',
        refY: '50%',
        x: 0,
        xAlign: 'middle',
        y: -7,
        yAlign: 'middle',
      },
      text: {
        fill: '#666',
        fontSize: 12,
        testWrap: null,
        text: '',
        refY: '115%',
      },
      image: {
        options: { category: 4, clusterNetworkID: 0 },
        'xlink:href': '',
      },
      '.rankCenter': {
        fill: '#ff0000',
        refX: '50%',
        refY: '0%',
        height: 20,
        width: 20,
        xAlign: 'middle',
        yAlign: 'top',
        'xlink:href': simulationCover('/computer/1.png'),
      },
      '.rank': {
        fill: '#909399',
      },
    };
    const nodeDetail = {
      id: '',
      position: {
        x: '',
        y: '',
      },
      size: {
        width: '',
        height: '',
      },
      attrs: commonAttrs,
      zIndex: resDetail.data.nodes[key].zIndex,
      ports: {
        groups: {
          bottom: {
            attrs: {
              circle: {
                fill: '#fff',
                magnet: true,
                r: 4,
                stroke: '#5F95FF',
                strokeWidth: 1,
                style: {
                  visibility: 'hidden',
                },
              },
            },
            position: 'bottom',
          },
          left: {
            attrs: {
              circle: {
                fill: '#fff',
                magnet: true,
                r: 4,
                stroke: '#5F95FF',
                strokeWidth: 1,
                style: {
                  visibility: 'hidden',
                },
              },
            },
            position: 'left',
          },
          right: {
            attrs: {
              circle: {
                fill: '#fff',
                magnet: true,
                r: 4,
                stroke: '#5F95FF',
                strokeWidth: 1,
                style: {
                  visibility: 'hidden',
                },
              },
            },
            position: 'right',
          },
          top: {
            attrs: {
              circle: {
                fill: '#fff',
                magnet: true,
                r: 4,
                stroke: '#5F95FF',
                strokeWidth: 1,
                style: {
                  visibility: 'hidden',
                },
              },
            },
            position: 'top',
          },
        },
        items: [],
      },
    };
    if (resDetail.data.nodes[key].shape) {
      nodeDetail['shape'] = resDetail.data.nodes[key].shape;
    }
    // 链接桩数据
    for (const k in resDetail.data.nodes[key].portInfo) {
      nodeDetail.ports.items.push({
        attrs: { circle: { style: { visibility: 'hidden' } } },
        id: resDetail.data.nodes[key].portInfo[k]['id'],
        group: resDetail.data.nodes[key].portInfo[k]['group'],
      });
    }
    // 节点数据
    nodeDetail.size.width = resDetail.data.nodes[key].width;
    nodeDetail.size.height = resDetail.data.nodes[key].height;
    nodeDetail.position.x = resDetail.data.nodes[key].x;
    nodeDetail.position.y = resDetail.data.nodes[key].y;
    nodeDetail.id = resDetail.data.nodes[key].id;
    // 内置组件属性处理
    if (resDetail.data.nodes[key].category === 5) {
      // 深拷贝赋值
      nodeDetail.attrs = cloneDeep(
        builtBaseNode[builtBaseNodeMap[resDetail.data.nodes[key].shape] + 1]
          .attrs,
      );

      nodeDetail.type = nodeDetail.attrs.image.options.type;

      if (!nodeDetail.attrs.text) {
        nodeDetail.attrs.text = {};
        nodeDetail.attrs.text.text = resDetail.data.nodes[key].name;
      } else {
        nodeDetail.attrs.text.text = resDetail.data.nodes[key].name;
      }
    } else {
      nodeDetail.attrs.text.text = resDetail.data.nodes[key].name;
      nodeDetail.attrs.image['xlink:href'] = resDetail.data.pic_host + (resDetail.data.nodes[
        key
      ].image.startsWith('/')
        ? resDetail.data.nodes[key].image
        : '/' + resDetail.data.nodes[key].image);
      nodeDetail.attrs['.rankCenter']['xlink:href'] = simulationCover(
        resDetail.data.nodes[key].computerImage,
      );
      nodeDetail.attrs['image']['options'] =
        resDetail.data.nodes[key].baseImage;
      if (resDetail.data.nodes[key].isGenerate) {
        nodeDetail.attrs['.rank'].fill = '#F56C6C';
        if (resDetail.data.nodes[key].isRunning) {
          nodeDetail.attrs['.rank'].fill = '#67C23A';
        }
      }
    }

    if (nodeDetail.attrs['image']['options']) {
      nodeDetail.attrs['image']['options']['uuid'] =
        resDetail.data.nodes[key].toolUUID;
      nodeDetail.attrs['image']['options']['config'] =
        resDetail.data.nodes[key].config;
      nodeDetail.attrs['image']['options']['cpu'] =
        resDetail.data.nodes[key].cores;
      nodeDetail.attrs['image']['options']['mem'] =
        resDetail.data.nodes[key].memory;
      nodeDetail.attrs['image']['options']['disk'] =
        resDetail.data.nodes[key].disk;
      nodeDetail.attrs['image']['options']['startConfig'] =
        resDetail.data.nodes[key].startConfig;
      nodeDetail.attrs['image']['options']['category'] =
        resDetail.data.nodes[key].category;
      nodeDetail.attrs['image']['options']['componentCategory'] =
        resDetail.data.nodes[key].componentCategory;
      nodeDetail.attrs['image']['options']['clusterNetworkID'] =
        resDetail.data.nodes[key].clusterNetworkID;
      nodeDetail.attrs['image']['options']['id'] =
        resDetail.data.nodes[key].rid;
    }
    topoData.nodes.push(nodeDetail);
  }
  // 连线数据
  for (const key in resDetail.data.edges) {
    let connector = !resDetail.data.edges[key].connector
      ? null
      : { name: resDetail.data.edges[key].connector };
    let router = !resDetail.data.edges[key].router
      ? null
      : { name: resDetail.data.edges[key].router };
    const linkDetail = {
      attrs: {
        line: {
          stroke: '#7a7979',
          targetMarker: {
            height: 10,
            name: 'block',
            width: 15,
          },
          strokeDasharray: 0,
        },
      },
      connector: connector,
      id: '',
      labels: [
        {
          attrs: {
            labelBody: {
              fill: '#fff',
              ref: 'labelText',
              refRx: '60%',
              refRy: '60%',
              stroke: '#5F95FF',
              strokeWidth: 1,
            },
            labelText: {
              fill: '#474747',
              text: 'e1',
              textAnchor: 'middle',
              textVerticalAnchor: 'middle',
            },
          },
          markup: [
            {
              selector: 'labelBody',
              tagName: 'ellipse',
            },
            {
              selector: 'labelText',
              tagName: 'text',
            },
          ],
          position: {
            distance: 0.1,
          },
        },
        {
          attrs: {
            labelBody: {
              fill: '#fff',
              ref: 'labelText',
              refRx: '60%',
              refRy: '60%',
              stroke: '#5F95FF',
              strokeWidth: 1,
            },
            labelText: {
              fill: '#474747',
              text: 'e1',
              textAnchor: 'middle',
              textVerticalAnchor: 'middle',
            },
          },
          markup: [
            {
              selector: 'labelBody',
              tagName: 'ellipse',
            },
            {
              selector: 'labelText',
              tagName: 'text',
            },
          ],
          position: {
            distance: 0.9,
          },
        },
      ],
      router: router,
      zIndex: resDetail.data.edges[key].zIndex,
      shape: 'edge',
      source: {
        cell: '',
        port: '',
      },
      target: {
        cell: '',
        port: '',
      },
      tools: null,
    };
    linkDetail.id = resDetail.data.edges[key].id;
    linkDetail.source = resDetail.data.edges[key].source;
    linkDetail.target = resDetail.data.edges[key].target;
    linkDetail.labels[0].attrs.labelText.text =
      resDetail.data.edges[key].portName[0];
    linkDetail.labels[1].attrs.labelText.text =
      resDetail.data.edges[key].portName[1];
    linkDetail.attrs.line.strokeDasharray =
      resDetail.data.edges[key].strokeDasharray;
    topoData.edges.push(linkDetail);
  }
  return topoData;
};
